﻿using InfonavaEye.common;
using InfonavaEye.handler;
using InfonavaEye.model;
using InfonavaEye.util;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace InfonavaEye.Forms
{
    public partial class AutoStartForm : Form
    {
        public event Action autoStartCloseDelegate;

        public event Action<string> selectTemplateDelegate;

        public string boxModelName;

        public BoxModel boxModel;

        public DeviceHandler deviceHandler;

        /// <summary>
        ///  选择钉盒模板时选中的钉子的字典
        /// </summary>
        private Dictionary<String, Nail> nailListToMap = null;

        /// <summary>
        /// 校准原点的位置（x,y）
        /// </summary>
        public Rectangle fixZeroLocation;

        public AutoStartForm(string templateName, List<Nail> oldTemplateNailList)
        {
            InitializeComponent();

            if (oldTemplateNailList != null)
            {
                this.boxModelName = templateName;
                this.nailListToMap = AutoStartParams.nailListToMap(oldTemplateNailList);
            }
        }

        private void btnSure_Click(object sender, EventArgs e)
        {
            this.boxModelName = this.cmbBox.Text;
            if (String.IsNullOrEmpty(this.boxModelName))
            {
                MessageBox.Show("请选择钉盒模型");
                return;
            }
            if (this.nailList == null || !this.nailList.Any(p => p.status == NailStatus.Selected))
            {
                MessageBox.Show("请选择要识别的钉子");
                return;
            }
            this.DialogResult = DialogResult.OK;
            this.Close();
        }

        private void btnBack_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void PickBoxModelForm_Load(object sender, EventArgs e)
        {
            var baseDir = FileHelper.getBaseDir();
            DirectoryInfo TheFolder = new DirectoryInfo(baseDir + "\\BoxModel");
            int selectIndex = 0;
            int i = 0;
            foreach (FileInfo file in TheFolder.GetFiles())
            {
                string itemText = file.Name.Replace(".json", "");
                this.cmbBox.Items.Add(itemText);
                if (this.nailListToMap != null && itemText.Equals(this.boxModelName))
                {
                    selectIndex = i;
                }
                i++;
            }
            //选中之前的模板
            Task.Factory.StartNew(async () =>
            {
                if (this.nailListToMap != null)
                {
                    try
                    {
                        await Task.Delay(500);
                        Console.WriteLine("选中之前的模板");
                        this.cmbBox.SelectedIndex = selectIndex;
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                }
            });
        }

        private void cmbBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            var item = this.cmbBox.SelectedItem;
            //解析钉盒模型
            this.boxModelName = item.ToString();
            if (this.selectTemplateDelegate != null)
            {
                this.selectTemplateDelegate.Invoke(this.boxModelName);
            }
            try
            {
                this.boxModel = BoxModelHelper.parseBoxModel(boxModelName);
                this.drawAreas();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        Color bgColor = Color.FromArgb(255, 233, 233, 233);
        private void picPreview_Paint(object sender, PaintEventArgs e)
        {
            var g = e.Graphics;
            GraphicsHelper.SetGDIHigh(g);
            GraphicsHelper.FillRoundRectangle(e.ClipRectangle, g, 15, bgColor);
        }

        Color mainColor = Color.FromArgb(255, 180, 180, 180);
        int margin = 600;
        int padding = 500;
        int nailWidth = 400;
        int nailHeight = 400;
        float scaleRate = 1 / 20f;
        //Dictionary<string, Nail> nailMap = new Dictionary<string, Nail>();
        public List<Nail> nailList = new List<Nail>();

        Graphics drawG = null;

        private void drawAreas()
        {
            if (this.boxModel == null) return;

            if (drawG != null)
            {
                drawG.Dispose();
            }

            nailList.Clear();
            int minX = (this.boxModel.boxAreas.Min(p => p.startPoint[0]));
            int minY = (this.boxModel.boxAreas.Min(p => p.startPoint[1]));
            int maxX = (this.boxModel.boxAreas.Max(p => p.startPoint[0]));
            int maxY = (this.boxModel.boxAreas.Max(p => p.startPoint[1]));
            int maxWidth = maxX - minX;
            int maxHeight = maxY - minY;
            int fixX = 0 - minX;
            int fixY = 0 - minY;

            this.boxModel.boxAreas.ForEach((area) =>
            {
                try
                {
                    Console.WriteLine("绘制区域:" + area.name);
                    var startPoint = area.startPoint;

                    //画外框
                    var x = startPoint[0] + fixX + margin;
                    var y = startPoint[1] + fixY + margin;
                    var width = area.holdPitch[0] * (area.columnCount - 1) + 2 * (padding);
                    var height = area.holdPitch[1] * (area.rowCount - 1) + 2 * (padding);
                    Console.WriteLine("绘制区域参数：x {0}，y {1},width {2},height {3}", x * scaleRate, y * scaleRate, width * scaleRate, height * scaleRate);
                    var areaPath = GraphicsHelper.DrawRoundRect((int)(x * scaleRate), (int)(y * scaleRate), (int)(width * scaleRate), (int)(height * scaleRate), 15);
                    drawG = picPreview.CreateGraphics();
                    GraphicsHelper.SetGDIHigh(drawG);
                    drawG.Clear(picPreview.BackColor);
                    drawG.DrawPath(new Pen(mainColor, 1), areaPath);
                    //画螺钉
                    for (int i = 0; i < area.columnCount; i++)
                    {
                        for (int j = 0; j < area.rowCount; j++)
                        {
                            width = nailWidth;
                            height = nailHeight;
                            if (i == 0 && j == 0)
                            {
                                width = (int)Math.Round(nailWidth * 1.5, 0);
                                height = (int)Math.Round(nailWidth * 1.5, 0);
                            }

                            x = startPoint[0] + fixX + area.holdPitch[0] * i + padding + margin - (width) / 2;
                            y = startPoint[1] + fixY + area.holdPitch[1] * j + padding + margin - (height) / 2;
                            Rectangle r = new Rectangle((int)(x * scaleRate), (int)(y * scaleRate), (int)(width * scaleRate), (int)(height * scaleRate));

                            var nailKey = string.Format(AutoStartParams.NAIL_MAP_KEY_FORMAT, area.code, i, j);
                            bool selected = (this.nailListToMap != null && this.nailListToMap.ContainsKey(nailKey) && this.nailListToMap[nailKey].status == NailStatus.Selected);

                            nailList.Add(new Nail()
                            {
                                status = selected ? NailStatus.Selected : NailStatus.Normal,
                                area = area,
                                point = new Point(i, j),
                                location = r,
                                updateTime = DateTime.Now,
                            });
                            Console.WriteLine("绘制钉子 ({0})：x {1}，y {2},width {3},height {4}", i + ":" + j, x * scaleRate, y * scaleRate, width * scaleRate, height * scaleRate);
                            drawG.DrawImage(selected ? Properties.Resources.nail_plus : Properties.Resources.nail_empty, r);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("绘制区域发生异常：{0}，{1}", ex.Message, ex.StackTrace);
                }
            });

        }

        private long prexMoveTimestamp = 0;
        private int prexX = 0;
        private int prexY = 0;
        private Nail preNail = null;
        private bool reDrawing = false;
        /// <summary>
        /// 手指经过每颗钉子 切换钉子状态
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void picPreview_MouseMove(object sender, MouseEventArgs e)
        {
            if (this.boxModel == null) return;
            Console.WriteLine("MouseMove,{0},{1}", DateTime.Now, DateTime.Now.Ticks / 100000 - prexMoveTimestamp);

            /* if (prexMoveTimestamp>0 && DateTime.Now.Ticks / 100000 - prexMoveTimestamp < 10) return;
             prexMoveTimestamp = DateTime.Now.Ticks / 100000;*/

            if (reDrawing) { Console.WriteLine("reDrawing return"); return; }
            reDrawing = true;

            try
            {

                Point dp = new Point(); //定义一个坐标结构
                dp.X = MousePosition.X; //用mousepostion获取鼠标在屏幕中的X轴位置
                dp.Y = MousePosition.Y;//用mousepostion获取鼠标在屏幕中的Y轴位置
                dp = picPreview.PointToClient(dp);  //this 屏幕点的位置转化成工作区坐标
                Console.WriteLine("dx:{0},dy:{1}", Math.Abs(prexX - dp.X), Math.Abs(prexX - dp.Y));
                if (!(Math.Abs(prexX - dp.X) > (int)(nailWidth * scaleRate) || Math.Abs(prexX - dp.Y) > (int)(nailHeight * scaleRate)))
                {
                    Console.WriteLine("dx dy return");
                    return;
                }
                prexX = dp.X;
                prexY = dp.Y;
                this.boxModel.boxAreas.ForEach((area) =>
                {
                    var startPoint = area.startPoint;

                    for (int i = 0; i < nailList.Count; i++)
                    {
                        var nail = nailList[i];
                        var minX = nail.location.X - nail.location.Width / 2 - padding * scaleRate / 3;
                        var maxX = nail.location.X + nail.location.Width / 2 + padding * scaleRate / 3;
                        var minY = nail.location.Y - nail.location.Height / 2 - padding * scaleRate / 3;
                        var maxY = nail.location.Y + nail.location.Height / 2 + padding * scaleRate / 3;
                        var point = nail.point;
                        if (dp.X >= minX && dp.X < maxX && dp.Y >= minY && dp.Y < maxY)
                        {
                            if (nail.Equals(preNail) && DateTimeUtil.dateDiffMs(DateTime.Now, nail.updateTime) < 600) return;
                            nail.updateTime = DateTime.Now;
                            preNail = nail;
                            nail.status = (nail.status == NailStatus.Normal) ? NailStatus.Selected : NailStatus.Normal;
                            var g = picPreview.CreateGraphics();
                            GraphicsHelper.SetGDIHigh(g);
                            GraphicsHelper.FillRoundRectangle(nail.location, g, 15, picPreview.BackColor);
                            Console.WriteLine("绘制钉子 ({0})：x {1}，y {2},width {3},height {4},status:{5}", point.X + ":" + point.Y, nail.location.X, nail.location.Y, nail.location.Width, nail.location.Height, nail.status);
                            var img = nail.status == NailStatus.Normal ? Properties.Resources.nail_empty : Properties.Resources.nail_plus;
                            Console.WriteLine("nail.status:" + nail.status);
                            g.DrawImage(Properties.Resources.nail_plus, nail.location);
                        }
                    }
                });
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                reDrawing = false;
            }
        }

        private void picPreview_MouseHover(object sender, EventArgs e)
        {

        }

        private void chbLightOnAll_CheckedChanged(object sender, EventArgs e)
        {
            if (this.boxModel == null || this.boxModel.boxAreas == null) return;

            this.boxModel.boxAreas.ForEach((area) =>
            {
                var startPoint = area.startPoint;

                for (int i = 0; i < nailList.Count; i++)
                {
                    var nail = nailList[i];
                    var minX = nail.location.X - nail.location.Width / 2 - padding * scaleRate / 3;
                    var maxX = nail.location.X + nail.location.Width / 2 + padding * scaleRate / 3;
                    var minY = nail.location.Y - nail.location.Height / 2 - padding * scaleRate / 3;
                    var maxY = nail.location.Y + nail.location.Height / 2 + padding * scaleRate / 3;
                    var point = nail.point;

                    nail.status = (chbLightOnAll.Checked) ? NailStatus.Selected : NailStatus.Normal;
                    var g = picPreview.CreateGraphics();
                    GraphicsHelper.SetGDIHigh(g);
                    GraphicsHelper.FillRoundRectangle(nail.location, g, 15, bgColor);
                    Console.WriteLine("绘制钉子 ({0})：x {1}，y {2},width {3},height {4},status:{5}", point.X + ":" + point.Y, nail.location.X, nail.location.Y, nail.location.Width, nail.location.Height, nail.status);
                    var img = nail.status == NailStatus.Normal ? Properties.Resources.nail_empty : Properties.Resources.nail_plus;
                    //Console.WriteLine("nail.status:" + nail.status);
                    g.DrawImage(img, nail.location);

                }
            });
        }

        private void AutoStartForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (autoStartCloseDelegate != null)
                autoStartCloseDelegate.Invoke();
        }
    }
}

